Waveform Generator |
A wave generator is an electronic device that can produce sine, triangular and squared signals. This device allows modifying the amplitude and the frequency of the signal produced. Un generador de audio es un dispositivo electrónico para producir ondas senoidales, triangulares y cuadradas. Este dispositivo permite modificar la amplitud y la frecuencia de la señal producida. |
Problem 1 |
Create a dialog application called AudioGen using Wintempla to create sine, triangular, saw tooth and rectangular signals. Once the application has been created, edit the stdafx.h file removing the comments from #define WIN_DAC_ADC_SUPPORT. Cree una aplicación de diálogo llamada AudioGen usando Wintempla que cree señales senoidales, triangulares, diente de sierra y rectangulares. Una vez creada la aplicación, edite el archivo stdafx.h removiendo el comentario de #define WIN_DAC_ADC_SUPPORT. |
Step A |
Open Wintempla, from the toolbar press the "Show All Controls in Toolbox" and insert a "Signal View" control as shown below. Set the name and the events as shown. In the Events tab, be sure all events are unselected. Abra Wintempla, y desde la barra de herramientas presione "Show All Controls in Toolbox" e inserte un condtrol de "Signal View" como se muestra debajo. Fije el nombre y eventos como se muestra. En la pestaña de eventos, asegúrese que todos los eventos están deseleccionados. |
Step B |
Open Wintempla, from the toolbar press the "Show All Controls in Toolbox" and insert a "Digital Analog Converter" as shown below. En la pestaña de eventos, asegúrese que todos los eventos están deseleccionados. Abra Wintempla, y desde la barra de herramientas presione "Show All Controls in Toolbox" e inserte un "Digital Analog Converter" como se muestra debajo. En la pestaña de eventos, asegúrese que todos los eventos están deseleccionados. |
Step C |
Complete the GUI as shown below. Insert four sliders to control the Amplitude and Frequency of each channel; add the Hscroll event to each slider. Insert four radio buttons for the signal type; add the Click event to each radio button. Finally, add a drop down list to choose the device. Complete the GUI como se muestra debajo. Inserte cuatro controles slider para la amplitud y la frecuencia de cada canal; agregue el evento Hscroll a cada slider. Inserte cuatro radio buttons para el tipo de señal, agregue el evento Click a cada radio button. Finalmente, agregue una lista desplegable para escoger el dispositivo. |
Step D |
Edit the AudioGen.h file and the AudioGen.cpp file to implement the three functions of the Mm::IAudioOut interface (Observe the the AudioGenclass is derived from Mm::IAudioOut). Remember that an interface is used to pass a set of functions to another function or another object. Edite los archivos AudioGen.h y AudioGen.cpp para implementar las tres funciones de la interface Mm::IAudioOut (Observa que la clase AudioGen se deriva de Mm::IAudioOut). Recuerde que una interface es usada para pasar un conjunto de funciones a otra función u objeto. |
AudioGen.h |
#pragma once //______________________________________ AudioGen.h #include "Resource.h" class AudioGen: public Win::Dialog, public Mm::IAudioOut { public: AudioGen() { frequency1 = 200.0; frequency2 = 200.0; amplitude1 = 10000; // For 8 bits: 0 to 127.5. For 16 bits: 0 to 32767 amplitude2 = 10000; // For 8 bits: 0 to 127.5. For 16 bits: 0 to 32767 signalType = SINE; } ~AudioGen() { } enum SignalType { SINE = 0, TRIANGULAR, SAWTOOTH, SQUARED }; SignalType signalType; double frequency1, frequency2; double amplitude1, amplitude2; static double Sawtooth(double x, double period); static double Triangular(double x, double period); static double Rectangular(double x, double period); void DisplayFrequency(void); //______________________________________________________________ Mm::IAudioOut void AudioOutStarted(unsigned int samplesPerSec, unsigned int numbChannels, unsigned int bitsResolution); void AudioOutData(unsigned int samplesPerSec, unsigned int numbChannels, unsigned int bitsResolution, WAVEHDR* waveHdr); void AudioOutStopped(); protected: ... }; |
AudioGen.cpp |
... void AudioGen::Window_Open(Win::Event& e) { //________________________________________________________ sldAmplitude1 sldAmplitude1.SetRange(0, 32760); sldAmplitude1.Position = (int)amplitude1; //________________________________________________________ sldFrequency sldFrequency1.SetRange(20, 20000); sldFrequency1.Position = (int)frequency1; //________________________________________________________ sldAmplitude2 sldAmplitude2.SetRange(0, 32760); sldAmplitude2.Position = (int)amplitude2; //________________________________________________________ sldFrequency2 sldFrequency2.SetRange(20, 20000); sldFrequency2.Position = (int)frequency2; //________________________________________________________ ddDevice const int count = ::waveOutGetNumDevs(); WAVEOUTCAPS woc; const int wsize= sizeof(WAVEOUTCAPS); for (int i = 0; i < count; i++) { if (::waveOutGetDevCaps(i, &woc, wsize) == MMSYSERR_NOERROR) { ddDevice.Items.Add(woc.szPname, i); } } ddDevice.SelectedIndex = 0; // btOff.Enabled = false; radioSine.Checked = true; } void AudioGen::AudioOutStarted(unsigned int samplesPerSec, unsigned int numbChannels, unsigned int bitsResolution) { this->EnableCloseButton(false); btOn.Enabled = false; btOff.Enabled = true; } void AudioGen::AudioOutStopped() { this->EnableCloseButton(true); btOn.Enabled = true; btOff.Enabled = false; } void AudioGen::AudioOutData(unsigned int samplesPerSec, unsigned int numbChannels, unsigned int bitsResolution, WAVEHDR* waveHdr) { Sys::Sample16 * data = (Sys::Sample16*)(waveHdr->lpData); const int bufferSize = waveHdr->dwBufferLength; const int sampleCount = bufferSize / 4; const int sampleRate = 44100; //Samples per second static double angle1 = 0; static double angle2 = 0; const double delta1 = 2.0*M_PI*frequency1 / sampleRate; const double delta2 = 2.0*M_PI*frequency2 / sampleRate; for (int i = 0; i<sampleCount; i++) { switch (signalType) { case SINE: data[i].channel_1 = (__int16)(amplitude1*sin(angle1)); data[i].channel_2 = (__int16)(amplitude2*sin(angle2)); break; case TRIANGULAR: data[i].channel_1 = (__int16)(amplitude1*Triangular(angle1, 2 * M_PI)); data[i].channel_2 = (__int16)(amplitude2*Triangular(angle2, 2 * M_PI)); break; case SQUARED: data[i].channel_1 = (__int16)(amplitude1*Rectangular(angle1, 2 * M_PI)); data[i].channel_2 = (__int16)(amplitude2*Rectangular(angle2, 2 * M_PI)); break; case SAWTOOTH: data[i].channel_1 = (__int16)(amplitude1*Sawtooth(angle1, 2 * M_PI)); data[i].channel_2 = (__int16)(amplitude2*Sawtooth(angle2, 2 * M_PI)); break; } angle1 += delta1; angle2 += delta2; if (angle1>2 * M_PI) angle1 -= 2 * M_PI; if (angle2>2 * M_PI) angle2 -= 2 * M_PI; } waveHdr->dwBytesRecorded = waveHdr->dwBufferLength; svMain.RefreshFromDAC(waveHdr, numbChannels, bitsResolution); } void AudioGen::sldAmplitude1_Hscroll(Win::Event& e) { const int position = sldAmplitude1.HasPositionChanged(); if (position < 0) return; amplitude1 = position; } void AudioGen::sldFrequency1_Hscroll(Win::Event& e) { const int position = sldFrequency1.HasPositionChanged(); if (position < 0) return; frequency1 = position; DisplayFrequency(); } void AudioGen::sldAmplitude2_Hscroll(Win::Event& e) { const int position = sldAmplitude2.HasPositionChanged(); if (position < 0) return; amplitude2 = position; } void AudioGen::sldFrequency2_Hscroll(Win::Event& e) { const int position = sldFrequency2.HasPositionChanged(); if (position < 0) return; frequency2 = position; DisplayFrequency(); } void AudioGen::btOn_Click(Win::Event& e) { this->DisplayFrequency(); //________________________________________________________ 1. Get the Device ID LPARAM deviceID = WAVE_MAPPER; ddDevice.GetSelectedData(deviceID); //________________________________________________________ 2. Start the DAC const wchar_t* error = dacMain.Start((unsigned int)deviceID, 44100, 2, 16, 16384, this); if (error != NULL) { this->MessageBox(error, L"AudioGen", MB_OK | MB_ICONERROR); } } void AudioGen::btOff_Click(Win::Event& e) { dacMain.Stop(); } void AudioGen::DisplayFrequency(void) { wchar_t caption[256]; _snwprintf_s(caption, 256, _TRUNCATE, L"f1 = %.0f Hz, f2 = %.0f Hz", frequency1, frequency2); this->SetWindowText(caption); } double AudioGen::Sawtooth(double x, double period) { const double half = period / 2.0; if (x == 0) return 0.0; if (x>0) while (x>half) x -= period; else while (x<half) x += period; return x / half; } double AudioGen::Triangular(double x, double period) { const double half = period / 2.0; if (x == 0) return 1.0; if (x>0) while (x>half) x -= period; else while (x<half) x += period; if (x>0) return -4.0*x / period + 1.0; else return 4.0*x / period + 1.0; return 0.0; } double AudioGen::Rectangular(double x, double period) { const double half = period / 2.0; if (x == 0) return 0.0; if (x>0) while (x>half) x -= period; else while (x<half) x += period; if (x>0) return 1.0; else return -1.0; return 0.0; } void AudioGen::radioSine_Click(Win::Event& e) { signalType = SINE; } void AudioGen::radioSquared_Click(Win::Event& e) { signalType = SQUARED; } void AudioGen::radioSawtooth_Click(Win::Event& e) { signalType = SAWTOOTH; } void AudioGen::radioTriangular_Click(Win::Event& e) { signalType = TRIANGULAR; } |
Step E |
Compile and run the program. Be sure to turn on the volume in the speakers. Compile y ejecute el programa. Asegúrese de tener encendidas las bocinas. |